﻿using System;
using System.Data.Odbc;
using System.Data.OleDb;
using System.Data.SqlClient;
using System.Diagnostics;
using System.Drawing.Printing;
using System.Globalization;
using System.IO;
using System.Net;
using System.Net.Mail;
using System.Net.NetworkInformation;
using System.Reflection;
using System.Security;
using System.Security.Permissions;
using System.Security.Policy;
using System.Web;
using System.Windows.Forms;

namespace ManagedSandbox
{
    public sealed partial class MainForm : Form
    {
        private AspNetHostingPermission _aspNetHostingPermission;
        private DnsPermission _dnsPermission;
        private EnvironmentPermission _environmentPermission;
        private EventLogPermission _eventLogPermission;
        private FileDialogPermission _fileDialogPermission;
        private FileIOPermission _fileIOPermission;
        private GacIdentityPermission _gacIdentityPermission;
        private IsolatedStorageFilePermission _isolatedStorageFilePermission;
        private KeyContainerPermission _keyContainerPermission;
        private NetworkInformationPermission _networkInformationPermission;

        private OdbcPermission _odbcPermission;
        private OleDbPermission _oleDbPermission;
        private PerformanceCounterPermission _performanceCounterPermission;
        private PrincipalPermission _principalPermission;
        private PrintingPermission _printingPermission;
        private PublisherIdentityPermission _publisherIdentityPermission;
        private ReflectionPermission _reflectionPermission;
        private RegistryPermission _registryPermission;
        private SecurityPermission _securityPermission;
        private SiteIdentityPermission _siteIdentityPermission;

        private SmtpPermission _smtpPermission;
        private SocketPermission _socketPermission;
        private SqlClientPermission _sqlClientPermission;
        private StorePermission _storePermission;
        private StrongNameIdentityPermission _strongNameIdentityPermission;
        private TypeDescriptorPermission _typeDescriptorPermission;
        private UIPermission _uiPermission;
        private UrlIdentityPermission _urlIdentityPermission;
        private WebPermission _webPermission;
        private ZoneIdentityPermission _zoneIdentityPermission;

        public MainForm()
        {
            InitializeComponent();

            string version = string.Format(CultureInfo.InvariantCulture, "{0}.{1}",
                                           Assembly.GetEntryAssembly().GetName().Version.Major,
                                           Assembly.GetEntryAssembly().GetName().Version.Minor);
            Text = string.Format(CultureInfo.InvariantCulture, Text, version);
        }

        private void assemblyButtonClick(object sender, EventArgs e)
        {
            if (DialogResult.OK != mOpenFileDialog.ShowDialog(this))
                return;

            assemblyTextBox.Text = mOpenFileDialog.FileName;
            runButton.Enabled = true;
        }

        private void unrestrictedCheckBoxCheckedChanged(object sender, EventArgs e)
        {
            permissionPanel.Enabled = !unrestrictedCheckBox.Checked;
        }

        private void aspNetHostingPermissionCheckBoxClick(object sender, EventArgs e)
        {
            _aspNetHostingPermission = aspNetHostingPermissionCheckBox.Checked ? new AspNetHostingPermission(PermissionState.Unrestricted) : null;
        }

        private void dnsPermissionCheckBoxClick(object sender, EventArgs e)
        {
            _dnsPermission = dnsPermissionCheckBox.Checked ? new DnsPermission(PermissionState.Unrestricted) : null;
        }

        private void environmentPermissionCheckBoxClick(object sender, EventArgs e)
        {
            _environmentPermission = environmentPermissionCheckBox.Checked ? new EnvironmentPermission(PermissionState.Unrestricted) : null;
        }

        private void eventLogPermissionCheckBoxClick(object sender, EventArgs e)
        {
            _eventLogPermission = eventLogPermissionCheckBox.Checked ? new EventLogPermission(PermissionState.Unrestricted) : null;
        }

        private void fileDialogPermissionCheckBoxClick(object sender, EventArgs e)
        {
            _fileDialogPermission = edit(new FileDialogPermissionForm(), _fileDialogPermission, fileDialogPermissionCheckBox) as FileDialogPermission;
        }

        private void fileIOPermissionCheckBoxClick(object sender, EventArgs e)
        {
            _fileIOPermission = fileIOPermissionCheckBox.Checked ? new FileIOPermission(PermissionState.Unrestricted) : null;
        }

        private void gacIdentityPermissionCheckBoxClick(object sender, EventArgs e)
        {
            _gacIdentityPermission = gacIdentityPermissionCheckBox.Checked ? new GacIdentityPermission(PermissionState.Unrestricted) : null;
        }

        private void isolatedStorageFilePermissionCheckBoxClick(object sender, EventArgs e)
        {
            _isolatedStorageFilePermission = isolatedStorageFilePermissionCheckBox.Checked ? new IsolatedStorageFilePermission(PermissionState.Unrestricted) : null;
        }

        private void keyContainerPermissionCheckBoxClick(object sender, EventArgs e)
        {
            _keyContainerPermission = keyContainerPermissionCheckBox.Checked ? new KeyContainerPermission(PermissionState.Unrestricted) : null;
        }

        private void networkInformationPermissionCheckBoxClick(object sender, EventArgs e)
        {
            _networkInformationPermission = networkInformationPermissionCheckBox.Checked ? new NetworkInformationPermission(PermissionState.Unrestricted) : null;
        }

        private void odbcPermissionCheckBoxClick(object sender, EventArgs e)
        {
            _odbcPermission = odbcPermissionCheckBox.Checked ? new OdbcPermission(PermissionState.Unrestricted) : null;
        }

        private void oleDbPermissionCheckBoxClick(object sender, EventArgs e)
        {
            _oleDbPermission = oleDbPermissionCheckBox.Checked ? new OleDbPermission(PermissionState.Unrestricted) : null;
        }

        private void performanceCounterPermissionCheckBoxClick(object sender, EventArgs e)
        {
            _performanceCounterPermission = performanceCounterPermissionCheckBox.Checked ? new PerformanceCounterPermission(PermissionState.Unrestricted) : null;
        }

        private void principalPermissionCheckBoxClick(object sender, EventArgs e)
        {
            _principalPermission = principalPermissionCheckBox.Checked ? new PrincipalPermission(PermissionState.Unrestricted) : null;
        }

        private void printingPermissionCheckBoxClick(object sender, EventArgs e)
        {
            _printingPermission = printingPermissionCheckBox.Checked ? new PrintingPermission(PermissionState.Unrestricted) : null;
        }

        private void publisherIdentityPermissionCheckBoxClick(object sender, EventArgs e)
        {
            _publisherIdentityPermission = publisherIdentityPermissionCheckBox.Checked ? new PublisherIdentityPermission(PermissionState.Unrestricted) : null;
        }

        private void reflectionPermissionCheckBoxClick(object sender, EventArgs e)
        {
            _reflectionPermission = reflectionPermissionCheckBox.Checked ? new ReflectionPermission(PermissionState.Unrestricted) : null;
        }

        private void registryPermissionCheckBoxClick(object sender, EventArgs e)
        {
            _registryPermission = registryPermissionCheckBox.Checked ? new RegistryPermission(PermissionState.Unrestricted) : null;
        }

        private void securityPermissionCheckBoxClick(object sender, EventArgs e)
        {
            _securityPermission = edit(new SecurityPermissionForm(), _securityPermission, securityPermissionCheckBox) as SecurityPermission;
        }

        private void siteIdentityPermissionCheckBoxClick(object sender, EventArgs e)
        {
            _siteIdentityPermission = siteIdentityPermissionCheckBox.Checked ? new SiteIdentityPermission(PermissionState.Unrestricted) : null;
        }

        private void smtpPermissionCheckBoxClick(object sender, EventArgs e)
        {
            _smtpPermission = smtpPermissionCheckBox.Checked ? new SmtpPermission(PermissionState.Unrestricted) : null;
        }

        private void socketPermissionCheckBoxClick(object sender, EventArgs e)
        {
            _socketPermission = socketPermissionCheckBox.Checked ? new SocketPermission(PermissionState.Unrestricted) : null;
        }

        private void sqlClientPermissionCheckBoxClick(object sender, EventArgs e)
        {
            _sqlClientPermission = sqlClientPermissionCheckBox.Checked ? new SqlClientPermission(PermissionState.Unrestricted) : null;
        }

        private void storePermissionCheckBoxClick(object sender, EventArgs e)
        {
            _storePermission = storePermissionCheckBox.Checked ? new StorePermission(PermissionState.Unrestricted) : null;
        }

        private void strongNameIdentityPermissionCheckBoxClick(object sender, EventArgs e)
        {
            _strongNameIdentityPermission = strongNameIdentityPermissionCheckBox.Checked ? new StrongNameIdentityPermission(PermissionState.Unrestricted) : null;
        }

        private void typeDescriptorPermissionCheckBoxClick(object sender, EventArgs e)
        {
            _typeDescriptorPermission = typeDescriptorPermissionCheckBox.Checked ? new TypeDescriptorPermission(PermissionState.Unrestricted) : null;
        }

        private void uiPermissionCheckBoxClick(object sender, EventArgs e)
        {
            _uiPermission = edit(new UIPermissionForm(), _uiPermission, uiPermissionCheckBox) as UIPermission;
        }

        private void urlIdentityPermissionCheckBoxClick(object sender, EventArgs e)
        {
            _urlIdentityPermission = urlIdentityPermissionCheckBox.Checked ? new UrlIdentityPermission(PermissionState.Unrestricted) : null;
        }

        private void webPermissionCheckBoxClick(object sender, EventArgs e)
        {
            _webPermission = webPermissionCheckBox.Checked ? new WebPermission(PermissionState.Unrestricted) : null;
        }

        private void zoneIdentityPermissionCheckBoxClick(object sender, EventArgs e)
        {
            _zoneIdentityPermission = zoneIdentityPermissionCheckBox.Checked ? new ZoneIdentityPermission(PermissionState.Unrestricted) : null;
        }

        private IPermission edit<TEditor>(TEditor editorForm, IPermission oldPermission, CheckBox checkBox)
            where TEditor : Form, IPermissionEditor, new()
        {
            editorForm.Initialize(oldPermission);
            var newPermission = DialogResult.OK == editorForm.ShowDialog(this)
                                            ? editorForm.Permission
                                            : oldPermission;

            checkBox.CheckState = editorForm.GetCheckState();

            return newPermission;
        }

        private void runButtonClick(object sender, EventArgs e)
        {
            // PermissionSet
            PermissionSet permissionSet;

            if (unrestrictedCheckBox.Checked)
            {
                permissionSet = new PermissionSet(PermissionState.Unrestricted);
            }
            else
            {
                permissionSet = new PermissionSet(PermissionState.None);

                if (null != _aspNetHostingPermission)
                    permissionSet.AddPermission(_aspNetHostingPermission);
                if (null != _dnsPermission)
                    permissionSet.AddPermission(_dnsPermission);
                if (null != _environmentPermission)
                    permissionSet.AddPermission(_environmentPermission);
                if (null != _eventLogPermission)
                    permissionSet.AddPermission(_eventLogPermission);
                if (null != _fileDialogPermission)
                    permissionSet.AddPermission(_fileDialogPermission);
                if (null != _fileIOPermission)
                    permissionSet.AddPermission(_fileIOPermission);
                if (null != _gacIdentityPermission)
                    permissionSet.AddPermission(_gacIdentityPermission);
                if (null != _isolatedStorageFilePermission)
                    permissionSet.AddPermission(_isolatedStorageFilePermission);
                if (null != _keyContainerPermission)
                    permissionSet.AddPermission(_keyContainerPermission);
                if (null != _networkInformationPermission)
                    permissionSet.AddPermission(_networkInformationPermission);

                if (null != _odbcPermission)
                    permissionSet.AddPermission(_odbcPermission);
                if (null != _oleDbPermission)
                    permissionSet.AddPermission(_oleDbPermission);
                if (null != _performanceCounterPermission)
                    permissionSet.AddPermission(_performanceCounterPermission);
                if (null != _principalPermission)
                    permissionSet.AddPermission(_principalPermission);
                if (null != _printingPermission)
                    permissionSet.AddPermission(_printingPermission);
                if (null != _publisherIdentityPermission)
                    permissionSet.AddPermission(_publisherIdentityPermission);
                if (null != _reflectionPermission)
                    permissionSet.AddPermission(_reflectionPermission);
                if (null != _registryPermission)
                    permissionSet.AddPermission(_registryPermission);
                if (null != _securityPermission)
                    permissionSet.AddPermission(_securityPermission);
                if (null != _siteIdentityPermission)
                    permissionSet.AddPermission(_siteIdentityPermission);

                if (null != _smtpPermission)
                    permissionSet.AddPermission(_smtpPermission);
                if (null != _socketPermission)
                    permissionSet.AddPermission(_socketPermission);
                if (null != _sqlClientPermission)
                    permissionSet.AddPermission(_sqlClientPermission);
                if (null != _storePermission)
                    permissionSet.AddPermission(_storePermission);
                if (null != _strongNameIdentityPermission)
                    permissionSet.AddPermission(_strongNameIdentityPermission);
                if (null != _typeDescriptorPermission)
                    permissionSet.AddPermission(_typeDescriptorPermission);
                if (null != _uiPermission)
                    permissionSet.AddPermission(_uiPermission);
                if (null != _urlIdentityPermission)
                    permissionSet.AddPermission(_urlIdentityPermission);
                if (null != _webPermission)
                    permissionSet.AddPermission(_webPermission);
                if (null != _zoneIdentityPermission)
                    permissionSet.AddPermission(_zoneIdentityPermission);
            }

            // -FileIOPermission
            permissionSet.AddPermission(new FileIOPermission(FileIOPermissionAccess.Read | FileIOPermissionAccess.PathDiscovery, assemblyTextBox.Text));

            // AppDomainSetup
            var appDomainSetup = new AppDomainSetup
                                     {
                                         ApplicationBase = Path.GetDirectoryName(assemblyTextBox.Text)
                                     };

            // AppDomain
            AppDomain appDomain = AppDomain.CreateDomain(
                "SandboxDomain",
                null,
                appDomainSetup,
                permissionSet,
                new StrongName[] {});

            try
            {
                appDomain.ExecuteAssemblyByName(Path.GetFileNameWithoutExtension(assemblyTextBox.Text));
            }
            catch (SecurityException exception)
            {
                MessageBox.Show(this, exception.Message, @"Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
            catch (FileLoadException exception)
            {
                if (exception.InnerException is PolicyException)
                    MessageBox.Show(this, exception.InnerException.Message, @"Error", MessageBoxButtons.OK,
                                    MessageBoxIcon.Error);
                else
                    throw;
            }
        }
    }
}